package priv.lhy.activity.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import priv.lhy.activity.commons.ResultResp;
import priv.lhy.activity.commons.ReturnCodeEnum;
import priv.lhy.activity.dal.entity.ActDrawAward;
import priv.lhy.activity.dal.entity.ActDrawAwardItem;
import priv.lhy.activity.dal.entity.ActDrawNum;
import priv.lhy.activity.dal.entity.ActDrawRecord;
import priv.lhy.activity.dal.persistence.ActDrawAwardItemMapper;
import priv.lhy.activity.dal.persistence.ActDrawAwardMapper;
import priv.lhy.activity.dal.persistence.ActDrawNumMapper;
import priv.lhy.activity.dal.persistence.ActDrawRecordMapper;
import priv.lhy.activity.draw.IActivityTurntableDrawService;
import priv.lhy.activity.draw.bean.ActivityTurntableDrawReq;
import priv.lhy.activity.draw.bean.AwardDrawRecordBean;
import priv.lhy.activity.services.processor.ActivityDrawContext;
import priv.lhy.activity.services.processor.ActivityTurntableDrawProxy;
import priv.lhy.activity.services.processor.constants.ActivityAPIConstants;
import priv.lhy.activity.services.processor.constants.DrawContants;
import priv.lhy.activity.services.processor.exception.RewardException;
import priv.lhy.activity.util.RedisKeyManager;
import priv.lhy.dto.UserQueryRequest;
import priv.lhy.user.IUserQueryService;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * author : lihy
 * date : 2019/2/16 9:08
 */
@Service("activityTurntableDrawService")
public class ActivityTurntableDrawServiceImpl implements IActivityTurntableDrawService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ActivityTurntableDrawServiceImpl.class);

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    ActDrawAwardItemMapper actDrawAwardItemMapper;

    @Autowired
    ActDrawAwardMapper actDrawAwardMapper;

    @Autowired
    ActDrawNumMapper actDrawNumMapper;

    @Autowired
    ActDrawRecordMapper actDrawRecordMapper;

    @Autowired
    ActivityTurntableDrawProxy activityTurntableDrawProxy;

    @Autowired
    IUserQueryService userQueryService;

    /**
     * 初始化奖品
     *
     * @throws Exception
     */
    @PostConstruct
    public void initDrawData() throws Exception {
        LOGGER.info("开始初始化奖品数据");
        //获得所有奖项：一等奖、二等奖、三等奖、。。。
        List<ActDrawAwardItem> awardItems = actDrawAwardItemMapper.queryAwardItem();
        if (awardItems == null || awardItems.isEmpty()) {
            throw new Exception("奖品数据未创建，初始化失败");
        }
        redisTemplate.opsForValue().set(DrawContants.DRAW_ITEM, awardItems);
        redisTemplate.expire(DrawContants.DRAW_ITEM, DrawContants.EXPIRE_TIME, TimeUnit.DAYS);
        //遍历所有奖项获得每个奖项对应的奖品
        for (ActDrawAwardItem item : awardItems) {
            ActDrawAward actDrawAward = actDrawAwardMapper.queryAwardById(item.getAwardId());
            redisTemplate.opsForValue().set(RedisKeyManager.getAwardRedisKey(actDrawAward), actDrawAward);
            redisTemplate.expire(RedisKeyManager.getAwardRedisKey(actDrawAward), DrawContants.EXPIRE_TIME, TimeUnit.DAYS);
            //TODO 如果奖品是有数量限制的，那么针对这类的奖品需要放到队列中
            //redisTemplate.opsForList().leftPush();
        }
    }

    @Override
    public ResultResp<AwardDrawRecordBean> doDraw(ActivityTurntableDrawReq activityTurntableDrawReq) {
        ResultResp<AwardDrawRecordBean> recordBeanResultResp = new ResultResp<>();

        try {
            //检测请求参数
            checkDrawParams(activityTurntableDrawReq);
            //设置抽奖上下文
            ActivityDrawContext context = new ActivityDrawContext();
            context.setActivityTurntableDrawReq(activityTurntableDrawReq);

            //设置抽奖用户
            UserQueryRequest userQueryRequest = new UserQueryRequest();
            userQueryRequest.setUid(activityTurntableDrawReq.getUid());
            context.setCurrenUser(userQueryService.getUserById(userQueryRequest));

            //抽奖
            activityTurntableDrawProxy.doDrawForProxy(context);

            //中奖记录
            AwardDrawRecordBean bean = new AwardDrawRecordBean();
            bean.setLevel(context.getActDrawAwardItem().getLevel());
            bean.setName(context.getCurrenUser().getRealName());
            bean.setUid(context.getActivityTurntableDrawReq().getUid());

            //设置返回信息
            recordBeanResultResp.setResult(bean);
            recordBeanResultResp.setReturnCodeEnum(ReturnCodeEnum.SUCCESS);
        } catch (Exception e) {
            LOGGER.error("抽奖失败！", e);
            recordBeanResultResp.setReturnCodeEnum(ReturnCodeEnum.SYSTEM_ERROR);
        } finally {
            LOGGER.info("抽奖请求{},响应{}", activityTurntableDrawReq, recordBeanResultResp);
            //清除正在抽奖标志缓存
            cleanRedisCache(activityTurntableDrawReq);
        }

        return recordBeanResultResp;
    }

    /**
     * 查询转盘抽奖剩余抽奖次数
     *
     * @param activityTurntableDrawReq
     * @return 大于0为抽奖次数，小于0为错误代码
     */
    @Override
    public int queryRemainDrawCount(ActivityTurntableDrawReq activityTurntableDrawReq) {
        ActDrawNum drawNum = actDrawNumMapper.queryDrawNumforUid(activityTurntableDrawReq.getUid());
        try {
            if (null != drawNum && drawNum.getMaxNumber() > 0) {
                return drawNum.getMaxNumber() - drawNum.getNowNumber();
            }
        } catch (Exception e) {
            LOGGER.error("查询抽奖次数异常", e);
            ActivityAPIConstants.IsAllowDrawCode.LUCK_DRAW_NOT_KNOW_DRAW.getValue();
        }
        return ActivityAPIConstants.IsAllowDrawCode.LUCK_DRAW_NOT_ALLOW.getValue();
    }

    /**
     * 查询中奖记录
     *
     * @param activityTurntableDrawReq
     * @return
     */
    @Override
    public List<AwardDrawRecordBean> queryAwardDrawRecord(ActivityTurntableDrawReq activityTurntableDrawReq) {
        if (null == activityTurntableDrawReq.getUid()) {
            throw new RuntimeException("uid不能为空");
        }
        List<AwardDrawRecordBean> beans = new ArrayList<>();
        List<ActDrawRecord> records = actDrawRecordMapper.queryDrawRecordList();
        for (int i = 0; i < records.size(); i++) {
            AwardDrawRecordBean bean = new AwardDrawRecordBean();
            bean.setUid(records.get(i).getUid());
            bean.setName(records.get(i).getName());
            bean.setLevel(records.get(i).getLevel());
            bean.setId(records.get(i).getId());
            bean.setMobile(records.get(i).getMobile());
            beans.add(bean);
        }
        return beans;
    }

    /**
     * 抽奖前验证
     *
     * @param request
     */
    private void checkDrawParams(ActivityTurntableDrawReq request) {
        if (null == request.getUid()) {
            throw new RewardException("uid不能为空");
        }
        Object value = redisTemplate.opsForValue().get(RedisKeyManager.getDrawingRedisKey(request));
        if (null != value && DrawContants.isexist.EXIST.getValue().equals(value)) {
            throw new RewardException("上一次抽奖还未结束");
        }

        //设置正在抽奖
        redisTemplate.opsForValue().set(RedisKeyManager.getDrawingRedisKey(request), DrawContants.isexist.EXIST.getValue());
        redisTemplate.expire(RedisKeyManager.getDrawingRedisKey(request), DrawContants.EXPIRE_TIME, TimeUnit.DAYS);
    }

    /**
     * 清除redis中正在抽奖的标记缓存
     *
     * @param request
     */
    private void cleanRedisCache(ActivityTurntableDrawReq request) {
        try {
            redisTemplate.delete(RedisKeyManager.getDrawingRedisKey(request));
        } catch (Exception e) {
            LOGGER.error("清除key[" + RedisKeyManager.getDrawingRedisKey(request) + "]异常", e);
        }
    }
}
